using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;

namespace dotnet_ef_admin.Src.Utilities;

public class JwtService {
    private readonly SymmetricSecurityKey _signingKey;

    // 构造函数，用于初始化密钥
    public JwtService(string key) {
        _signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
    }

    // 生成 JWT token 的方法
    public string GenerateToken(int userId) {
        // 定义 JWT token 的声明
        var claims = new[] {
            new Claim("userId", userId.ToString()), // 用户 ID
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), // JWT ID
            new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(),
                ClaimValueTypes.Integer64) // 发行时间
        };

        var creds = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);

        // 创建 JWT token
        var token = new JwtSecurityToken(
            "yourIssuer", // 发行者
            "yourAudience", // 受众
            claims,
            expires: DateTime.UtcNow.AddHours(1), // 过期时间
            signingCredentials: creds); // 签名凭证

        // 返回生成的 JWT token
        return new JwtSecurityTokenHandler().WriteToken(token);
    }

    // 验证 JWT token 的方法
    public ClaimsPrincipal ValidateToken(string token) {
        var tokenHandler = new JwtSecurityTokenHandler();
        var validationParameters = GetTokenValidationParameters();

        try {
            // 验证 token 并返回包含用户声明的 ClaimsPrincipal 对象
            var principal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);
            return principal;
        } catch (Exception) {
            // 抛出应用程序异常，表示 token 无效
            throw new ApplicationException("无效的 token。");
        }
    }

    // 从 JWT token 中提取用户 ID 的方法
    public int GetUserIdFromToken(string token) {
        var tokenHandler = new JwtSecurityTokenHandler();
        var validationParameters = GetTokenValidationParameters();

        try {
            // 验证 token 并返回包含用户声明的 ClaimsPrincipal 对象
            var principal = tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);
            // 提取用户 ID 声明
            var userIdClaim = principal.FindFirst("userId");
            if (userIdClaim != null && int.TryParse(userIdClaim.Value, out var userId))
                return userId;
            throw new ApplicationException("未找到或无效的 UserId 声明。");
        } catch (SecurityTokenValidationException ex) {
            // 输出详细的异常信息以便调试
            Console.WriteLine($"Token 验证失败: {ex.Message}");
            throw new ApplicationException("Token 验证失败。", ex);
        } catch (Exception ex) {
            // 输出详细的异常信息以便调试
            Console.WriteLine($"验证 token 失败: {ex.Message}");
            throw new ApplicationException("无效的 token。", ex);
        }
    }

    // 获取 token 验证参数的方法
    public TokenValidationParameters GetTokenValidationParameters() {
        return new TokenValidationParameters {
            ValidateIssuerSigningKey = true, // 验证发行者签名密钥
            IssuerSigningKey = _signingKey,
            ValidateIssuer = false, // 不验证发行者
            ValidateAudience = false, // 不验证受众
            ValidateLifetime = true, // 验证生命周期
            ClockSkew = TimeSpan.Zero // 不允许时间偏差
        };
    }
}